# -*- coding: utf-8 -*-
#
# Copyright (C) 2011  Benjamin Heil
#
# This file is part of Feedmail.
#
# Feedmail is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import feedparser

from django.test import TestCase, Client
from django.core.urlresolvers import reverse
from parser import *
from models import FeedItem, FeedError, FeedAbo
from account.tests import add_testuser

TEST_RAW_FEEDDATA = """<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-de">
    <title>FeedMail-TestFeed</title>
    <link href="http://www.bheil.net/" rel="alternate"></link>
    <link href="http://www.bheil.net/blog/atom.xml" rel="self"></link>
    <id>http://www.bheil.net/</id>
    <updated>2010-11-28T16:51:47+01:00</updated>
    <subtitle>There's no other place like /home (bheil.net-Blog-Feed)</subtitle>
    <entry>
        <title>Feedmail - Nachrichtenfeeds per Mail empfangen</title>
        <link href="http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/" rel="alternate"></link>
        <updated>2010-11-28T16:51:47+01:00</updated>
        <id>http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/</id>
        <summary type="html">
            Ich möchte hier kurz auf eine Seite hinweisen, die ich gerade online gestellt habe:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://feedmail.bheil.net"&gt;http://feedmail.bheil.net&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In aller Kürze macht die Seite folgendes:&lt;br /&gt;&lt;strong&gt;Feedmail ruft regelmäßig Nachrichtenfeeds (RSS, Atom) von Webseiten ab und verschickt jeden neuen Eintrag per Mail an Deine Adresse.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Da ein Bild mehr als 1000 Worte sagt, hier ein Beispiel, wie so eine Mail aussehen kann:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;
            &lt;img src="http://static.kendoo.bheil.net/201034318/imagehost/spiegel-online__feedmail_1.png" alt="Beispielmail" /&gt;
            &lt;/div&gt;&lt;br /&gt;Weitere Infos und für was das überhaupt gut sein soll, gibts auf der Seite selbst. Dort ist auch eine &lt;a href="http://feedmail.bheil.net/faq.html"&gt;FAQ&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ich habe das in erster Linie für mich selbst entwickelt, aber vielleicht nützt es ja auch sonst wem.
        </summary>
        <category term="feedmail"></category>
    </entry>
    <item>
        <title>Le procès en appel de l'explosion d'AZF s'ouvrira le 3 novembre</title>
        <link>http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208</link>
        <description>En novembre 2009, le tribunal correctionnel de Toulouse avait prononcé une relaxe générale. Le parquet avait alors fait appel.&lt;img width='1' height='1' src='http://rss.feedsportal.com/c/205/f/3050/s/1153d02a/mf.gif' border='0'/&gt;</description>
        <enclosure url="http://s2.lemde.fr/image/2009/02/23/87x0/1159020_7_8279_l-explosion-de-l-usine-azf-le-21-septembre.jpg" length="1999" type="image/jpeg" />
        <pubDate>Thu, 06 Jan 2011 12:24:34 GMT</pubDate>
        <guid isPermaLink="false">http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208</guid>
    </item>
    <item>
        <title><![CDATA[AD: 田舎に行こう]]></title>
        <link>http://www.pheedo.jp/feeds/ht.php?t=c&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4</link>
        <description><![CDATA[<table border="0" cellpadding="0" cellspacing="0">
            <tr><td style="font-size:0.9em;" valign="top">自然とのふれあい、企業の植樹活動など、各地の「グリーンツーリズム」をご紹介します。</td></tr>
            <tr><td style="font-size:0.9em;"><a href="http://www.pheedo.jp/feeds/ht.php?t=c&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4">mainichi.jp/life/travel/green/</a></td></tr>
            </table>
            <div style="font-size:xx-small; padding-top: 1em;"><span style="border-top: 1px solid">
            <br style="display:none"/>
            Ads by Pheedo</span><img alt="" style="border: 0;" border="0" src="http://www.pheedo.jp/feeds/ht.php?t=v&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4"/>
            <br/>
            </div>
        ]]></description>
        <pubDate>Thu, 06 Jan 2011 12:24:34 GMT</pubDate>
        <category term="田舎に行こう"></category>
        <category term="自然とのふれあい、企業の植樹活動など、"></category>
    </item>
    <entry>
        <title>HTC steigert Umsatz und Gewinn</title>
        <link href="http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10" />
        <id>http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10</id>
        <published>2011-01-06T14:40:00+01:00</published>
        <updated>2011-01-06T14:42:28+01:00</updated>
    </entry>
</feed>"""

class TestParserFunctions(TestCase):
    def setUp(self):
        self.data = feedparser.parse(TEST_RAW_FEEDDATA)

    def test_getFeedName_0(self):
        self.assertEqual(getFeedName(''), u'noname')

    def test_getFeedName_1(self):
        self.assertEqual(getFeedName(TEST_RAW_FEEDDATA), u'FeedMail-TestFeed')

    def test_getFeedName_2(self):
        self.assertNotEqual(getFeedName(TEST_RAW_FEEDDATA), u'Wrong Title')

    def test_getEntryContent_0(self):
        self.assertEqual(getEntryContent(self.data.entries[0]),
                         ('HTML', u'Ich m\xf6chte hier kurz auf eine Seite hinweisen, die ich gerade online gestellt habe:<br /><br /><a href="http://feedmail.bheil.net">http://feedmail.bheil.net</a><br /><br />In aller K\xfcrze macht die Seite folgendes:<br /><strong>Feedmail ruft regelm\xe4\xdfig Nachrichtenfeeds (RSS, Atom) von Webseiten ab und verschickt jeden neuen Eintrag per Mail an Deine Adresse.</strong><br /><br />Da ein Bild mehr als 1000 Worte sagt, hier ein Beispiel, wie so eine Mail aussehen kann:<br /><br /><div style="text-align: center;">\n            <img alt="Beispielmail" src="http://static.kendoo.bheil.net/201034318/imagehost/spiegel-online__feedmail_1.png" />\n            </div><br />Weitere Infos und f\xfcr was das \xfcberhaupt gut sein soll, gibts auf der Seite selbst. Dort ist auch eine <a href="http://feedmail.bheil.net/faq.html">FAQ</a>.<br /><br />Ich habe das in erster Linie f\xfcr mich selbst entwickelt, aber vielleicht n\xfctzt es ja auch sonst wem.'))
                         #('HTML', u'Ich m\xf6chte hier kurz auf eine Seite hinweisen, die ich gerade online gestellt habe:<br /><br /><a href="http://feedmail.bheil.net">http://feedmail.bheil.net</a><br /><br />In aller K\xfcrze macht die Seite folgendes:<br /><strong>Feedmail ruft regelm\xe4\xdfig Nachrichtenfeeds (RSS, Atom) von Webseiten ab und verschickt jeden neuen Eintrag per Mail an Deine Adresse.</strong><br /><br />Da ein Bild mehr als 1000 Worte sagt, hier ein Beispiel, wie so eine Mail aussehen kann:<br /><br /><div>\n            <img src="http://static.kendoo.bheil.net/201034318/imagehost/spiegel-online__feedmail_1.png" alt="Beispielmail" />\n            </div><br />Weitere Infos und f\xfcr was das \xfcberhaupt gut sein soll, gibts auf der Seite selbst. Dort ist auch eine <a href="http://feedmail.bheil.net/faq.html">FAQ</a>.<br /><br />Ich habe das in erster Linie f\xfcr mich selbst entwickelt, aber vielleicht n\xfctzt es ja auch sonst wem.'))

    def test_getEntryContent_1(self):
        self.assertEqual(getEntryContent(self.data.entries[1]),
                         ('HTML', u'En novembre 2009, le tribunal correctionnel de Toulouse avait prononc\xe9 une relaxe g\xe9n\xe9rale. Le parquet avait alors fait appel.<img border="0" height="1" src="http://rss.feedsportal.com/c/205/f/3050/s/1153d02a/mf.gif" width="1" />'))

    def test_getEntryContent_2(self):
        self.assertEqual(getEntryContent(self.data.entries[2]),
                         ('HTML', u'<table border="0" cellpadding="0" cellspacing="0">\n            <tr><td style="font-size: 0.9em;" valign="top">\u81ea\u7136\u3068\u306e\u3075\u308c\u3042\u3044\u3001\u4f01\u696d\u306e\u690d\u6a39\u6d3b\u52d5\u306a\u3069\u3001\u5404\u5730\u306e\u300c\u30b0\u30ea\u30fc\u30f3\u30c4\u30fc\u30ea\u30ba\u30e0\u300d\u3092\u3054\u7d39\u4ecb\u3057\u307e\u3059\u3002</td></tr>\n            <tr><td style="font-size: 0.9em;"><a href="http://www.pheedo.jp/feeds/ht.php?t=c&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4">mainichi.jp/life/travel/green/</a></td></tr>\n            </table>\n            <div style="font-size: xx-small; padding-top: 1em;"><span style="border-top: 1px solid;">\n            <br style="display: none;" />\n            Ads by Pheedo</span><img alt="" border="0" src="http://www.pheedo.jp/feeds/ht.php?t=v&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4" style="border: 0;" />\n            <br />\n            </div>'))

    def test_getEntryContent_3(self):
        self.assertEqual(getEntryContent(self.data.entries[3]), '')

    def test_getEntryFingerprint_0(self):
        self.assertEqual(getEntryFingerprint(self.data.entries[0]),
                         u'http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/')
        
    def test_getEntryFingerprint_1(self):
        self.assertEqual(getEntryFingerprint(self.data.entries[1]),
                         u'http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208')
        
    def test_getEntryFingerprint_2(self):
        self.assertEqual(getEntryFingerprint(self.data.entries[2]),
                         '5e05bc9bee0220a4fdf3fc36f8ad7a8a')
        
    def test_getEntryFingerprint_3(self):
        self.assertEqual(getEntryFingerprint(self.data.entries[3]),
                         u'http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10')

    def test_getEntryFingerprint_MD5_0(self):
        self.assertEqual(getEntryFingerprint_MD5(self.data.entries[0]),
                         u'9328d8f0850bd1903bff23d4f123627f')

    def test_getEntryFingerprint_MD5_1(self):
        self.assertEqual(getEntryFingerprint_MD5(self.data.entries[1]),
                         u'fb5060c1ee9ea7e993f3b092f5f2a2e0')

    def test_getEntryFingerprint_MD5_2(self):
        self.assertEqual(getEntryFingerprint_MD5(self.data.entries[2]),
                         'b033452209778606eade9cc25c243b4f')

    def test_getEntryFingerprint_MD5_3(self):
        self.assertEqual(getEntryFingerprint_MD5(self.data.entries[3]),
                         u'cf1df6f6db44492d55652ddec6929684')

    def test_getEntryTitle_0(self):
        self.assertEqual(getEntryTitle(self.data.entries[0]),
                         u'Feedmail - Nachrichtenfeeds per Mail empfangen')

    def test_getEntryTitle_1(self):
        self.assertEqual(getEntryTitle(self.data.entries[1]),
                         u"Le proc\xe8s en appel de l'explosion d'AZF s'ouvrira le 3 novembre")

    def test_getEntryTitle_2(self):
        self.assertEqual(getEntryTitle(self.data.entries[2]),
                         u'AD: \u7530\u820e\u306b\u884c\u3053\u3046')

    def test_getEntryTitle_3(self):
        self.assertEqual(getEntryTitle(self.data.entries[3]),
                         u'HTC steigert Umsatz und Gewinn')

    def test_getEntryBody_0(self):
        self.assertEqual(getEntryBody(self.data.entries[0], getEntryTitle(self.data.entries[0])),
                         u'\n<html>\n<head><style><!-- h1{font-size:12pt;font-weight:bold;}body{font:11pt Ubuntu,Verdana,Arial;}a:link{color:#0066CC;}a:hover{color:#88BB22;}code{font-family:monospace;}blockquote,pre{border:1px solid #DADADA;background-color:#EEE;-moz-border-radius:4px;padding:8px;font-family:monospace;}#footer{margin-top:16px;padding:8px;-moz-border-radius:4px;background-color:#EEE;border:1px solid #DADADA;color:#444;}#feedmail-footer{float:right;font-size:xx-small;margin-bottom: 4px;color:#999;}#feedmail-footer a{color:#999;} //--></style></head>\n<body>\n<h1 id="header"><a href="http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/">Feedmail - Nachrichtenfeeds per Mail empfangen</a></h1>\nIch m\xf6chte hier kurz auf eine Seite hinweisen, die ich gerade online gestellt habe:<br /><br /><a href="http://feedmail.bheil.net">http://feedmail.bheil.net</a><br /><br />In aller K\xfcrze macht die Seite folgendes:<br /><strong>Feedmail ruft regelm\xe4\xdfig Nachrichtenfeeds (RSS, Atom) von Webseiten ab und verschickt jeden neuen Eintrag per Mail an Deine Adresse.</strong><br /><br />Da ein Bild mehr als 1000 Worte sagt, hier ein Beispiel, wie so eine Mail aussehen kann:<br /><br /><div style="text-align: center;">\n            <img alt="Beispielmail" src="http://static.kendoo.bheil.net/201034318/imagehost/spiegel-online__feedmail_1.png" />\n            </div><br />Weitere Infos und f\xfcr was das \xfcberhaupt gut sein soll, gibts auf der Seite selbst. Dort ist auch eine <a href="http://feedmail.bheil.net/faq.html">FAQ</a>.<br /><br />Ich habe das in erster Linie f\xfcr mich selbst entwickelt, aber vielleicht n\xfctzt es ja auch sonst wem.\n<div id="footer">Quelle: <a href="http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/">http://www.bheil.net/blog/2010/11/28/feedmail-nachrichtenfeeds-mail-empfangen/</a></div>\n<div id="feedmail-footer">Mail generiert von <a href="%s">Feedmail</a></div>\n</body></html>\n' % settings.ROOT_URL)

    def test_getEntryBody_1(self):
        self.assertEqual(getEntryBody(self.data.entries[1], getEntryTitle(self.data.entries[1])),
                         u'\n<html>\n<head><style><!-- h1{font-size:12pt;font-weight:bold;}body{font:11pt Ubuntu,Verdana,Arial;}a:link{color:#0066CC;}a:hover{color:#88BB22;}code{font-family:monospace;}blockquote,pre{border:1px solid #DADADA;background-color:#EEE;-moz-border-radius:4px;padding:8px;font-family:monospace;}#footer{margin-top:16px;padding:8px;-moz-border-radius:4px;background-color:#EEE;border:1px solid #DADADA;color:#444;}#feedmail-footer{float:right;font-size:xx-small;margin-bottom: 4px;color:#999;}#feedmail-footer a{color:#999;} //--></style></head>\n<body>\n<h1 id="header"><a href="http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208">Le proc\xe8s en appel de l\'explosion d\'AZF s\'ouvrira le 3 novembre</a></h1>\nEn novembre 2009, le tribunal correctionnel de Toulouse avait prononc\xe9 une relaxe g\xe9n\xe9rale. Le parquet avait alors fait appel.<img border="0" height="1" src="http://rss.feedsportal.com/c/205/f/3050/s/1153d02a/mf.gif" width="1" />\n<div id="footer">Quelle: <a href="http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208">http://www.lemonde.fr/societe/article/2011/01/06/le-proces-en-appel-de-l-explosion-d-azf-s-ouvrira-le-3-novembre_1461966_3224.html#xtor=RSS-3208</a><br/>Anhang: <a href="http://s2.lemde.fr/image/2009/02/23/87x0/1159020_7_8279_l-explosion-de-l-usine-azf-le-21-septembre.jpg">http://s2.lemde.fr/image/2009/02/23/87x0/1159020_7_8279_l-explosion-de-l-usine-azf-le-21-septembre.jpg</a>\n</div>\n<div id="feedmail-footer">Mail generiert von <a href="%s">Feedmail</a></div>\n</body></html>\n' % settings.ROOT_URL)

    def test_getEntryBody_2(self):
        pass
        #self.assertEqual(getEntryBody(self.data.entries[2], getEntryTitle(self.data.entries[2])),
        #                 u'\n<html>\n<head><style><!-- h1{font-size:12pt;font-weight:bold;}body{font:11pt Ubuntu,Verdana,Arial;}a:link{color:#0066CC;}a:hover{color:#88BB22;}code{font-family:monospace;}blockquote,pre{border:1px solid #DADADA;background-color:#EEE;-moz-border-radius:4px;padding:8px;font-family:monospace;}#footer{margin-top:16px;padding:8px;-moz-border-radius:4px;background-color:#EEE;border:1px solid #DADADA;color:#444;}#feedmail-footer{float:right;font-size:xx-small;margin-bottom: 4px;color:#999;}#feedmail-footer a{color:#999;} //--></style></head>\n<body>\n<h1 id="header"><a href="http://www.pheedo.jp/feeds/ht.php?t=c&ampi=95c8552d91ad995d6b9031b41302702d&ampp=4">AD: \u7530\u820e\u306b\u884c\u3053\u3046</a></h1>\n<table border="0" cellpadding="0" cellspacing="0">\n            <tr><td style="font-size: 0.9em;" valign="top">\u81ea\u7136\u3068\u306e\u3075\u308c\u3042\u3044\u3001\u4f01\u696d\u306e\u690d\u6a39\u6d3b\u52d5\u306a\u3069\u3001\u5404\u5730\u306e\u300c\u30b0\u30ea\u30fc\u30f3\u30c4\u30fc\u30ea\u30ba\u30e0\u300d\u3092\u3054\u7d39\u4ecb\u3057\u307e\u3059\u3002</td></tr>\n            <tr><td style="font-size: 0.9em;"><a href="http://www.pheedo.jp/feeds/ht.php?t=c&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4">mainichi.jp/life/travel/green/</a></td></tr>\n            </table>\n            <div style="font-size: xx-small; padding-top: 1em;"><span style="border-top: 1px solid;">\n            <br style="display: none;" />\n            Ads by Pheedo</span><img alt="" border="0" src="http://www.pheedo.jp/feeds/ht.php?t=v&amp;i=95c8552d91ad995d6b9031b41302702d&amp;p=4" style="border: 0;" />\n            <br />\n            </div>\n<div id="footer">Quelle: <a href="http://www.pheedo.jp/feeds/ht.php?t=c&ampi=95c8552d91ad995d6b9031b41302702d&ampp=4">http://www.pheedo.jp/feeds/ht.php?t=c&ampi=95c8552d91ad995d6b9031b41302702d&ampp=4</a></div>\n<div id="feedmail-footer">Mail generiert von <a href="%s">Feedmail</a></div>\n</body></html>\n' % settings.ROOT_URL)

    def test_getEntryBody_3(self):
        self.assertEqual(getEntryBody(self.data.entries[3], getEntryTitle(self.data.entries[3])),
                         u'\n<html>\n<head><style><!-- h1{font-size:12pt;font-weight:bold;}body{font:11pt Ubuntu,Verdana,Arial;}a:link{color:#0066CC;}a:hover{color:#88BB22;}code{font-family:monospace;}blockquote,pre{border:1px solid #DADADA;background-color:#EEE;-moz-border-radius:4px;padding:8px;font-family:monospace;}#footer{margin-top:16px;padding:8px;-moz-border-radius:4px;background-color:#EEE;border:1px solid #DADADA;color:#444;}#feedmail-footer{float:right;font-size:xx-small;margin-bottom: 4px;color:#999;}#feedmail-footer a{color:#999;} //--></style></head>\n<body>\n<h1 id="header"><a href="http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10">HTC steigert Umsatz und Gewinn</a></h1>\n\n<div id="footer">Quelle: <a href="http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10">http://www.heise.de/newsticker/meldung/HTC-steigert-Umsatz-und-Gewinn-1164559.html/from/atom10</a></div>\n<div id="feedmail-footer">Mail generiert von <a href="%s">Feedmail</a></div>\n</body></html>\n' % settings.ROOT_URL)

    def test_getEntryTags_0(self):
        self.assertEqual(getEntryTags(self.data.entries[0]), u'feedmail')

    def test_getEntryTags_1(self):
        self.assertEqual(getEntryTags(self.data.entries[1]), u'')

    def test_getEntryTags_2(self):
        self.assertEqual(getEntryTags(self.data.entries[2]), u'\u7530\u820e\u306b\u884c\u3053\u3046,\u81ea\u7136\u3068\u306e\u3075\u308c\u3042\u3044\u3001\u4f01\u696d\u306e\u690d\u6a39\u6d3b\u52d5\u306a\u3069\u3001')

    def test_getEntryTags_3(self):
        self.assertEqual(getEntryTags(self.data.entries[3]), u'')

class TestFeedManagerViews(TestCase):

    def setUp(self):
        add_testuser(self, username='testmanager_user', password='password', mail='testmanager_user@bheil.net')
        login = self.client.login(username='testmanager_user', password='password')
        self.failUnless(login, 'Could not log in')

    def test_add_feed(self):
        url = reverse('feedmanager_add_feed')

        # GET should return 403 Forbidden
        response = self.client.get(url)
        self.assertEqual(response.status_code, 403)

        response = self.client.post(url, {'url': 'http://www.bheil.net/blog/atom.xml'})
        self.assertEqual(response.status_code, 200)

    def test_get_feed_table(self):
        url = reverse('feedmanager_dashboard')
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'reload_dashboard()')
        self.assertContains(response, 'reload_errorlog(page)')
        self.assertContains(response, 'remove_feed(id)')
        self.assertContains(response, '<div id="feed-table">')
        
    def test_get_errorlog(self):
        url = reverse('feedmanager_errorlog')
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'reload_dashboard()')
        self.assertContains(response, 'reload_errorlog(page)')
        self.assertContains(response, 'remove_feed(id)')
        self.assertContains(response, '<div id="feed-table">')
        
    def test_errorlog_pagination(self):
        # Create a test user
        user = add_testuser(self, username='test_errorlog_pagination', password='test_errorlog_pagination', mail='test_errorlog_pagination@bheil.net')
        # Create a feed
        feed = FeedItem(url=settings.TEST_FEED_URL)
        feed.save()
        # Set a relationship between the feed and the test user
        abo = FeedAbo(user=user, feed=feed)
        abo.save()
        # Create some fake errors for our test feed
        for i in range(0, settings.PAGINATION_ITEMS_PER_PAGE * 3):
            error = FeedError(feed=feed, error_no=i, msg='Error %s' % i, url=feed.url)
            error.save()
        # Login with the test user
        login = self.client.login(username='test_errorlog_pagination', password='test_errorlog_pagination')
        self.failUnless(login, 'Could not log in')
        # Get the error table with the fake errors like the ajax request
        # would fetch it            
        url = reverse('feedmanager_get_error_table') + '?page=2'
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        
    def test_addfeed(self):
        user = add_testuser(self, username='test_addfeed', password='test_addfeed', mail='test_addfeed@bheil.net')
        login = self.client.login(username='test_addfeed', password='test_addfeed')
        url = reverse('feedmanager_add_feed')
        
        # GET should be forbidden
        response = self.client.get(url)
        self.assertEqual(response.status_code, 403)
        
        # POST should work as expected and create a FeedItem- and FeedAbo-entry
        response = self.client.post(url, data={'url': settings.TEST_FEED_URL})
        self.assertEqual(response.status_code, 200)
        try:
            feed = FeedItem.objects.get(url=settings.TEST_FEED_URL)
        except FeedItem.DoesNotExist:
            self.fail('Feed item should exist at this point')
        try:
            abo = FeedAbo.objects.get(feed=feed, user=user)
        except FeedAbo.DoesNotExist:
            self.fail('No abo was created for test feed and test user')
        
    def test_removefeed(self):
        user = add_testuser(self, username='test_removefeed', password='test_removefeed', mail='test_removefeed@bheil.net')
        login = self.client.login(username='test_removefeed', password='test_removefeed')
        self.failUnless(login, 'Could not log in')
        # Create a feed
        feed = FeedItem(url=settings.TEST_FEED_URL)
        feed.save()
        # Set a relationship between the feed and the test user
        abo = FeedAbo(user=user, feed=feed)
        abo.save()
        url = reverse('feedmanager_remove_feed')
        
        # A query with a wrong ID should be forbidden
        response = self.client.get(url + '?id=73676535636')
        self.assertEqual(response.status_code, 403)
        
        # A query with the right ID should work as expected
        response = self.client.get('%s?id=%s' % (url, feed.id))
        self.assertEqual(response.status_code, 200)
        try:
            abo = FeedAbo.objects.get(user=user, feed=feed)
            self.fail('Abo was not removed in feedmanager_remove_feed')
        except FeedAbo.DoesNotExist:
            pass
        # Since this was the last abo, even the feed itself should be gone now
        try:
            f = FeedItem.objects.get(id=feed.id)
            self.fail('FeedItem still exists')
        except FeedItem.DoesNotExist:
            pass

    def test_get_feed_table(self):
        # Create a test user
        user = add_testuser(self, username='test_get_feed_table', password='test_get_feed_table', mail='test_get_feed_table@bheil.net')
        # Create a feed
        feed = FeedItem(url=settings.TEST_FEED_URL)
        feed.save()
        # Set a relationship between the feed and the test user
        abo = FeedAbo(user=user, feed=feed)
        abo.save()
        login = self.client.login(username='test_get_feed_table', password='test_get_feed_table')
        self.failUnless(login, 'Could not log in')
        url = reverse('feedmanager_get_feed_table')
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<tr id=\\"feed%s\\">' % feed.id)
        self.assertContains(response, '<td id=\\"feed%s_name\\" class=\\"feed-list-name\\">%s</td>' % (feed.id, feed.name))
        self.assertContains(response, '<a href=\\"%s\\">%s</a>' % (feed.url, feed.url))
        self.assertContains(response, '<button type=\\"button\\" onclick=\\"javascript:remove_feed(%s);\\">' % feed.id)